package codegenerator;

import java.io.Serializable;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import baytony.util.Util;
import baytony.util.log.Log;
import codegenerator.config.DataBaseConfigration;

@SuppressWarnings("serial")
public class GeneratorHelper implements Serializable {

	private static final Logger logger = Log.getLogger();
	private DataBaseConfigration configration;
	private List<TableInfo> tables;
	private static final String TABLE_TYPE = "TABLE_TYPE";
	private static final String TABLE_NAME = "TABLE_NAME";
	private static final String COLUMN_NAME = "COLUMN_NAME";
	private static final String COLUMN_TYPE = "TYPE_NAME";
	private static final String COLUMN_SIZE = "COLUMN_SIZE";
	private static final String REMARKS = "REMARKS";
	private static final String TABLE = "TABLE";

	@Autowired
	@Qualifier("DataBaseConfigration")
	public void setConfigration(DataBaseConfigration configration) {
		this.configration = configration;
	}

	/**
	 * 初始化
	 */
	public void init() {
		ResultSet rs = null;
		Connection connection = null;
		try {
			Class.forName(configration.getDriver());
			connection = DriverManager.getConnection(configration.getUrl(), configration.getAccount(), configration.getPassword());
			DatabaseMetaData dbmd = connection.getMetaData();
			rs = dbmd.getTables(null, null, null, null);
			if (rs != null) {
				tables = new ArrayList<TableInfo>();
				TableInfo table = null;
				while (rs.next()) {
					if (!TABLE.equals(rs.getString(TABLE_TYPE))) {
						continue;
					}
					table = new TableInfo();
					String tableName = rs.getString(TABLE_NAME);
					table.setName(tableName);
					tables.add(table);
				}
			}
			for (TableInfo table : tables) {
				rs = dbmd.getPrimaryKeys(null, null, table.getName());
				List<String> primaryKeys = null;
				if (rs != null) {
					primaryKeys = new ArrayList<String>();
					while (rs.next()) {
						String columnName = rs.getString(COLUMN_NAME);
						primaryKeys.add(columnName);
					}
				}
				rs = dbmd.getColumns(null, null, table.getName(), null);
				if (rs != null) {
					List<ColumnInfo> columns = new ArrayList<ColumnInfo>();
					List<ColumnInfo> primaryKeyColumns = new ArrayList<ColumnInfo>();
					ColumnInfo column = null;
					while (rs.next()) {
						column = new ColumnInfo();
						String columnName = rs.getString(COLUMN_NAME);
						String type = rs.getString(COLUMN_TYPE);						
						int size = rs.getInt(COLUMN_SIZE);
						String remark = rs.getString(REMARKS);
						column.setName(columnName);
						column.setType(type);
						column.setSize(size);
						column.setRemark(remark);
						if (isPrimaryKey(primaryKeys, column))
							primaryKeyColumns.add(column);
						else
							columns.add(column);
					}
					table.setPrimaryKey(primaryKeyColumns);
					table.setColumns(columns);
				}
			}
		} catch (Exception e) {
			logger.error(e.getMessage());
			Log.logStackTrace(e);
		} finally {
			if(rs != null) {
				try {
					rs.close();
				} catch (SQLException e) {
					logger.error(e.getMessage());
					Log.logStackTrace(e);
				}
			}
			if (connection != null) {
				try {
					connection.close();
				} catch (SQLException e) {
					logger.error(e.getMessage());
					Log.logStackTrace(e);
				}
			}
		}
	}

	/**
	 * 判斷是否為 primary key
	 *
	 * @param primaryKeys
	 * @param column
	 * @return
	 */
	private static boolean isPrimaryKey(List<String> primaryKeys, ColumnInfo column) {
		String columnName = column.getName();
		if (primaryKeys.contains(columnName)) {
			return true;
		}
		return false;
	}

	/**
	 * 取得所有的 table
	 *
	 * @return
	 */
	public List<TableInfo> getTables() {
		return tables;
	}

	/**
	 * 取得指定的table
	 *
	 * @param tableName
	 * @return
	 */
	public TableInfo getTable(String tableName) {
		TableInfo result = null;
		if(!Util.isEmptyList(tables)) {
			for (TableInfo table : tables) {
				if (table.getName().equalsIgnoreCase(tableName)) {
					result = table;
					break;
				}
			}
		}
		return result;
	}
	
	/**
	 * 取得所有欄位但不包含 primary key
	 *
	 * @param tableName
	 * @return
	 */
	public List<ColumnInfo> getColumnsNoPk(String tableName) {
		List<ColumnInfo> result = null;
		if (tables != null) {
			for (TableInfo table : tables) {
				if (tableName.equalsIgnoreCase(table.getName())) {
					result = new ArrayList<ColumnInfo>();
					result.addAll(table.getColumns());
					break;
				}
			}
		}
		return result;
	}
	
	/**
	 * 取得專案名稱
	 *
	 * @return
	 */
	public String getProjectName() {
		return configration.getProjectName();
	}
	
	/**
	 * 取得範本檔案位置
	 *
	 * @return
	 */
	public String getJtmpPath() {
		return configration.getJtmpPath();
	}
	
	/**
	 * 取得.java輸出位置
	 *
	 * @return
	 */
	public String getOutputPath() {
		return configration.getOutputPath();
	}
	
	/**
	 * 取得檔案編碼
	 *
	 * @return
	 */
	public String getFileEncode() {
		return configration.getFileEncode();
	}
	
	/**
	 * 取得專案src路徑
	 *
	 * @return
	 */
	public String getSrcPath() {
		return configration.getSrcPath();
	}
	
	/**
	 * 取得.jsp輸出位置
	 *
	 * @return
	 */
	public String getPageOutputPath() {
		return configration.getPageOutputPath();
	}
	
	/**
	 * 取得config檔輸出位置
	 *
	 * @return
	 */
	public String getConfigOutputPath() {
		return configration.getConfigOutputPath();
	}
	
	/**
	 * 取得 driver
	 *
	 * @return
	 */
	public String getDriver() {
		return configration.getDriver();
	}
	
	/**
	 * 取得連線帳號
	 *
	 * @return
	 */
	public String getConnectAcc() {
		return configration.getAccount();
	}
	
	/**
	 * 取得連線密碼
	 *
	 * @return
	 */
	public String getConnectPw() {
		return configration.getPassword();
	}
	
	/**
	 * 取得 jdbc url
	 *
	 * @return
	 */
	public String getJdbcUrl() {
		return configration.getUrl();
	}
	
	public String getCssOutputPath() {
		return configration.getCssOutputpath();
	}
	
	public String getPackageScanPath() {
		return configration.getPackageScan();
	}
	
	public String getPackageVoScanPath() {
		return configration.getPackageScan() + ".vo";
	}
	
	public String getGenerationType() {
		return configration.getGenerationType();
	}
}
